﻿namespace JoinBox.Forms;

using System;
using System.Windows.Forms;

/// <summary>
/// 窗口控件子类化
/// </summary>
public class NativeCallProc : NativeWindow, IDisposable
{
    Func<Message, bool>? WndProcEvent;

    /// <summary>
    /// 窗口控件子类化<br/>
    /// 声明一定要写到类成员上,否则导致GC不确定的释放,从而触发析构
    /// </summary>
    /// <param name="intPtr">窗体句柄</param>
    public NativeCallProc(IntPtr intPtr)
    {
        this.AssignHandle(intPtr);
    }

    /// <summary>
    /// 消息循环:传委托进去不断替换
    /// </summary>
    /// <param name="WndProc">消息,true不拦截回调</param>
    public void WndProc(Func<Message, bool> WndProc)
    {
        WndProcEvent = WndProc;
    }

#line hidden
    // 此处会不断的执行消息循环
    protected override void WndProc(ref Message msg)
    {
        if (WndProcEvent is null)
            return;
        if (WndProcEvent.Invoke(msg))
            base.WndProc(ref msg);
    }
#line default

    #region IDisposable接口相关函数
    public bool IsDisposed { get; private set; } = false;

    /// <summary>
    /// 手动调用释放
    /// </summary>
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    /// <summary>
    /// 析构函数调用释放
    /// </summary>
    ~NativeCallProc()
    {
        Dispose(false);
    }

    protected virtual void Dispose(bool disposing)
    {
        // 不重复释放,并设置已经释放
        if (IsDisposed) return;
        IsDisposed = true;

        // 释放占用窗体的句柄
        ReleaseHandle();
    }
    #endregion
}